package com.example.successfox.myapplication;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import de.tavendo.autobahn.WebSocketConnection;
import de.tavendo.autobahn.WebSocketException;
import de.tavendo.autobahn.WebSocketHandler;

public class MainActivity extends AppCompatActivity {

    private final static String TAG = "MainActivity";
    private Button mBtnView;
    private Button mBtnLive;
    private ImageView mImageView;

    private boolean mSendConnectionOpend = false;

    private WebSocketConnection mConnection = new WebSocketConnection();

    private Camera mCamera;
    private SurfaceHolder mHolder;
    private SurfaceView mSurfaceView;

    private Camera.PreviewCallback mPreviewCallback = new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] bytes, Camera camera) {
            Log.i(TAG, "onPreviewFrame.");

            decodeToBitMap(bytes, camera);

        }
    };

    private SurfaceHolder.Callback mCallback = new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            Log.i(TAG, "surfaceCreated.");
            if(mCamera == null) {
                mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);
                try {
                    mCamera.setPreviewDisplay(mHolder);//通过surfaceview显示取景画面
                    mCamera.setPreviewCallback(mPreviewCallback);

                    Camera.Parameters parameters = mCamera.getParameters();
                    parameters.setPreviewSize(320, 240);
                    mCamera.setParameters(parameters);
                    mCamera.startPreview();//开始预览
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
            Log.i(TAG, "surfaceChanged.");
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
            Log.i(TAG, "surfaceDestroyed.");
            if (mCamera != null) {
                mCamera.release();
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtnView = (Button) this.findViewById(R.id.btn_connect);
        mBtnView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (mConnection.isConnected()) {
                    return;
                }
                connect();
            }
        });

        mImageView = (ImageView) this.findViewById(R.id.image);

        mBtnLive = (Button) this.findViewById(R.id.btn_live);
        mBtnLive.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                live();
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mConnection != null && mConnection.isConnected()) {
            mConnection.disconnect();
            mConnection = null;
        }
    }

    public void decodeToBitMap(byte[] data, Camera camera) {
        Camera.Size size = mCamera.getParameters().getPreviewSize();
        try {
            YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width,
                    size.height, null);
            Log.i(TAG, size.width + " " + size.height);
            if (image != null) {
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                image.compressToJpeg(new Rect(0, 0, size.width, size.height),
                        80, stream);
                Bitmap bmp = BitmapFactory.decodeByteArray(
                        stream.toByteArray(), 0, stream.size());
                String base64 = "data:image/jpeg;base64," + bitmapToBase64(bmp);

                if (mSendConnectionOpend) {
                    mConnection.sendTextMessage(base64);
                }
                stream.close();
            }
        } catch (Exception ex) {
            Log.e(TAG, "Error:" + ex.getMessage());
        }
    }

    private void live() {
        final String wsuri = "ws://192.168.2.233:8080";
        try {
            mConnection.connect(wsuri, new WebSocketHandler() {
                @Override
                public void onOpen() {
                    Log.i(TAG, "onOpen.");
                    mSendConnectionOpend = true;
                }
            });
        } catch (WebSocketException e) {

        }

        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
        mSurfaceView.setVisibility(View.VISIBLE);
        mImageView.setVisibility(View.GONE);
        mHolder = mSurfaceView.getHolder();//获得句柄
        mHolder.addCallback(mCallback);//添加回调
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public static String bitmapToBase64(Bitmap bitmap) {

        String result = null;
        ByteArrayOutputStream baos = null;
        try {
            if (bitmap != null) {
                baos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);

                baos.flush();
                baos.close();

                byte[] bitmapBytes = baos.toByteArray();
                result = Base64.encodeToString(bitmapBytes, Base64.DEFAULT);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (baos != null) {
                    baos.flush();
                    baos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        Log.i(TAG, "base64 = "+result);
        return result;
    }


    private void connect() {
        mImageView.setVisibility(View.VISIBLE);

        final String wsuri = "ws://192.168.2.233:8008";
        try {
            mConnection.connect(wsuri, new WebSocketHandler() {

                @Override
                public void onOpen() {
                    Log.i(TAG, "Status: Connected to " + wsuri);
                }

                @Override
                public void onTextMessage(String payload) {
                    String encodedDataString = payload;
                    encodedDataString = encodedDataString.replace("data:image/jpeg;base64,", "");
                    byte[] imageAsBytes = Base64.decode(encodedDataString.getBytes(), Base64.DEFAULT);
                    Bitmap bmp = BitmapFactory.decodeByteArray(
                            imageAsBytes, 0, imageAsBytes.length);
                    Log.i(TAG, "bmp width = " + bmp.getWidth() + " height = " + bmp.getHeight());
                    mImageView.setImageBitmap(bmp);
                }

                @Override
                public void onClose(int code, String reason) {
                    Log.d(TAG, "Connection lost.");
                }

                @Override
                public void onBinaryMessage(byte[] payload) {
                    Log.i(TAG, "onBinaryMessage.");
                }

                @Override
                public void onRawTextMessage(byte[] payload) {
                    Log.i(TAG, "onRawTextMessage.");
                }
            });
        } catch (WebSocketException e) {

            Log.i(TAG, e.toString());
        }
    }

}